home *** CD-ROM | disk | FTP | other *** search
/ Aminet 19 / Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso / Aminet / comm / tcp / Crak.lha / craksort2.c < prev    next >
C/C++ Source or Header  |  1997-02-28  |  12KB  |  487 lines

  1. /*
  2. VERSION: 0.01 by Sudog Feb '97
  3. So what if I have a non-standard version?
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <string.h>
  8. #ifdef AMIGA
  9. #include <dos/dos.h>
  10. #include <exec/memory.h>
  11. #endif
  12.  
  13. /* duh */
  14. #define TRUE        1  /* generic true/false because I don't want to waste time */
  15. #define FALSE       0  /* including exec/types.h so there. */
  16.  
  17. /* the following for passwd structure traversal */
  18. #define USER        1  /* at user field in line */
  19. #define PASSWD      2  /* at passwd field in passwd entry */
  20. #define SAVE        3  /* after storing user & password, save it */
  21. #define DONE        4  /* and after saving it for later, skip over rest */
  22.  
  23. /* maximum values for internal passwd structure */
  24. #define NAMESIZE   15  /* for struct passwd and for parsepass routine */
  25. #define SALTSIZE    3
  26. #define PASSWDSIZE 14
  27. #define WORDSIZE   20  /* maximum size of password in command line or password in dictfile */
  28.  
  29. /* values for return() from getnextdict */
  30. #define DICT_DONE  1   /* dictionary has been exhausted */
  31. #define DICT_ERROR 2   /* dictionary file is corrupt or something else just as fucked up */
  32.  
  33.  
  34. #define SEPARATOR  ':' /* passwd field separator.. : for unix, | for AmiTCP */
  35.  
  36. /*
  37. ** This is merely a small affectation because I am sometimes curious
  38. ** to have regular status updates..  uncomment this #define if you like
  39. ** something happening everytime the dictionary file has been entirely
  40. ** searched through..
  41. */
  42. #define ANIMSIZE   4
  43.  
  44. #ifdef AMIGA
  45. int CXBRK(void) {return(0);}    /* sorry user we're gonna make SURE that you can't */
  46. int chkabort(void) {return(0);} /* mess us up without giving us chance to clean up */
  47. #endif
  48.  
  49. struct passwd
  50.   {
  51.   char name[NAMESIZE];
  52.   char salt[SALTSIZE];
  53.   char password[PASSWDSIZE];
  54.   struct passwd *nextitem;
  55.   struct passwd *lastitem;
  56.   short cracked;
  57.   };
  58.  
  59. FILE *dictionary;  /* global because we want getnextdict() to have an open-and-ready */
  60.                    /* file handle from which to read words from the dictionary when in */
  61.                    /* dictionary mode */
  62.  
  63. char *crypt(char *, char *);
  64. struct passwd *parsepass(char *);
  65. void cleanup(struct passwd *);
  66. void log(char *, char *, char *);
  67. long getnextdict(char *, char *);
  68.  
  69. int main(int argc, char *argv[])
  70. {
  71. unsigned int counter;
  72. unsigned int c=FALSE;
  73. unsigned char commandword[WORDSIZE];
  74.  
  75. struct passwd *firstitem=NULL;
  76. struct passwd *currentitem=NULL;
  77.  
  78. long status; /* for returns from various functions..  scratchpad */
  79.  
  80. #ifdef ANIMSIZE
  81. char anim[] = "\\|/-";
  82. int animcounter = 0;
  83. #endif
  84.  
  85. #ifdef AMIGA
  86. long actualsigs;
  87. long waitmask = SIGBREAKF_CTRL_C;
  88. #endif
  89.  
  90. dictionary=NULL; /* i don't want to do this more than once */
  91.  
  92. /* do some command line argument parsing */
  93. /* this is hereby hard-coded.*/
  94. for (counter = 0; counter < argc; counter++)
  95.   {
  96.   if (argv[counter][0] == '-')
  97.     {
  98. /*
  99. ** The following accepts the - as an indicator, and then it copies the
  100. ** rest of this particular argument as a word to search a passwd file for.
  101. ** The reason this isn't hard-coded as argv[2] is for future expandability--
  102. ** sort of a functional work-in-progress.
  103. */
  104.     c = TRUE;
  105.     for (counter=1; counter < WORDSIZE; counter++)
  106.       {
  107.       commandword[counter-1] = argv[2][counter];
  108.       if (commandword[counter-1] == 0) break;
  109.       }
  110.     break;
  111.     }
  112.   if (argv[counter][0] == '?')
  113.     {
  114. /*
  115. ** I could never really see the harm in goto statements within programs.
  116. ** "A Book On C" says that goto statements are bad programming pratice.
  117. ** Whatever..
  118. */
  119. usage:
  120.     printf("Usage: %s <passwdfile> -<word> [outputfile]\n", argv[0]);
  121.     printf("       %s <passwdfile> <dictfile> [outputfile]\n", argv[0]);
  122.     printf("       %s ?\n", argv[0]);
  123.     printf("This program written in Feb, '97 by sudog.\n");
  124.     printf("So there.\n");
  125.     exit(0);
  126.     }
  127.   }
  128.  
  129. counter = 0;
  130.  
  131. if (argc > 2)
  132.   {
  133.   if (firstitem = parsepass(argv[1]))
  134.     {
  135.     currentitem = firstitem;
  136. /*
  137. ** This section deals with a command-line supplied password.
  138. */
  139.     if (c)
  140.       {
  141.       while (currentitem != NULL)
  142.         {
  143.         if (!strcmp(currentitem->password, crypt(commandword, currentitem->salt)))
  144.           {
  145.           printf("%s %s\n", currentitem->name, commandword);
  146.           if (argc > 3)
  147.              {
  148.             log(argv[3], currentitem->name, commandword);
  149.             }
  150.           }
  151. /* This section is amiga-only--it allows the user to break the program,
  152. ** CLEANLY! (Ie: We trap SIGBREAKF_CTRL_C and clean up the memory we allocated.)
  153. */
  154. #ifdef AMIGA
  155.         actualsigs = CheckSignal(waitmask);
  156.         if (actualsigs)
  157.           {
  158.           cleanup(firstitem);
  159.           }
  160. #endif
  161.         currentitem = currentitem->nextitem;
  162.         }
  163.       }
  164. /*
  165. ** This section deals with a dictionary file!
  166. ** TODO:
  167. ** Add place holder so a system crash can be survived and iterations can
  168. ** continue from last point...  VERY cool. let's do som background cracking!
  169. */
  170. /*
  171. ** First priority is to check the entire dictionary against the 
  172. ** current passwd entry. It's MUCH MUCH INCREDIBLY FASTER then.
  173. */
  174.     else
  175.       {
  176.       currentitem=firstitem;
  177. /*
  178. ** A simple while loop to search an entire dictionary on a single
  179. ** password entry. Trust me, this saves a SHITLOAD of time, since
  180. ** for each new salt which is used, crypt() has to re-set all its
  181. ** damned data structure and shit. VERY crappy. Otherwise it zips
  182. ** through things in like, 500 keys per second. At least, on my
  183. ** machine, compared with maybe 10 keys/sec otherwise.
  184. */
  185.       while ( currentitem != NULL )
  186.         {
  187.         while (((status=getnextdict(commandword, argv[2])) != DICT_DONE) && (status != DICT_ERROR))
  188.           {
  189.           if (!currentitem->cracked)
  190.             {
  191.             if (!strcmp(currentitem->password, crypt(commandword, currentitem->salt)))
  192.               {
  193.               printf("%s %s\n", currentitem->name, commandword);
  194.               currentitem->cracked = TRUE;
  195.               if (argc > 3)
  196.                 {
  197.                 log(argv[3], currentitem->name, commandword);
  198.                 }
  199.               }
  200.             }
  201. #ifdef AMIGA
  202.           actualsigs = CheckSignal(waitmask);
  203.           if (actualsigs)
  204.             {
  205.             cleanup(firstitem);
  206.             }
  207. #endif
  208.           }
  209.         if (status == DICT_ERROR)
  210.           {
  211.           printf("Error: Unable to access dictionary file..\n");
  212.           break;
  213.           }
  214.         if (status == DICT_DONE)
  215.           {
  216. #ifdef ANIMSIZE
  217.           printf("%c%c", anim[animcounter], 8);
  218.           animcounter++;
  219.           if (animcounter >= ANIMSIZE)
  220.             {
  221.             animcounter = 0;
  222.             }
  223. #endif
  224.           }
  225.         currentitem=currentitem->nextitem;
  226.         }
  227.       }
  228.     }
  229.   else
  230.     {
  231.     printf("Error in parsing password file.\n");
  232.     }
  233.   }
  234. else
  235.   {
  236.   printf("Error. You don't have a clue. Here. Have one.\n");
  237.   goto usage;
  238.   }
  239.  
  240. cleanup(firstitem);
  241.  
  242. }
  243.  
  244. /*
  245. ** In order that we get dictionary words, we have to 
  246. ** return words in cyclical order. Ie: We have to 
  247. ** get the first word after we got the last word.
  248. ** So we aren't returning any end-of-file conditions.
  249. ** We're just returning words unless an error
  250. ** condition exists.
  251. */
  252.  
  253. long getnextdict(char *commandword, char *filename)
  254. {
  255. long counter=0;
  256. int gotone=FALSE;
  257. char temp;
  258.  
  259. if (commandword == NULL && filename == NULL)
  260.   {
  261.   if (dictionary)
  262.     {
  263.     fclose(dictionary);
  264.     }
  265.   return(0);
  266.   }
  267. if (!dictionary)
  268.   {
  269.   if (!(dictionary = fopen(filename, "r")))
  270.     {
  271.     return(DICT_ERROR);
  272.     }
  273.   }
  274. if (dictionary)
  275.   {
  276.   while ( 1 )
  277.     {
  278.     temp = fgetc(dictionary);
  279.     if (feof(dictionary))
  280.       {
  281.       if (gotone)
  282.         {
  283.         commandword[counter] = 0;
  284.         return(0);
  285.         }
  286.       else
  287.         {
  288. /*
  289. ** We're going to re-use the dictionary file again and again and
  290. ** again until we're TOLD to close it with getnextdict(NULL, NULL);
  291. */
  292.         rewind(dictionary);
  293.         return(DICT_DONE);
  294.         }
  295.       }
  296.     else if (temp > 31 && temp < 127)
  297.       {
  298.       if (gotone == FALSE)
  299.         {
  300.         gotone = TRUE;
  301.         }
  302.       if (counter < WORDSIZE)
  303.         {
  304.         commandword[counter++] = temp;
  305.         }
  306.       }
  307.     else
  308.       {
  309.       if (gotone == TRUE)
  310.         {
  311.         commandword[counter] = 0;
  312.         return(0);
  313.         }
  314.       }
  315.     } /* end of while loop */
  316.   }
  317. }
  318.  
  319. /*
  320. ** Excellently enough, calloc() remembers how big the memory chunks
  321. ** it allocated are, so a call to free() doesn't have to specify anything
  322. ** but the pointer!!  ANSI-C rules!
  323. */
  324. void cleanup(struct passwd *firstitem)
  325. {
  326. struct passwd *currentitem;
  327. while (firstitem != NULL)
  328.   {
  329.   currentitem = firstitem->nextitem;
  330.   free(firstitem);
  331.   firstitem = currentitem;
  332.   }
  333. getnextdict(NULL, NULL);
  334. exit(0);
  335. }
  336.   
  337. void log (char *filename, char *username, char *password)
  338. {
  339. FILE *output;
  340.  
  341. if (output = fopen(filename, "a"))
  342.   {
  343.   fprintf(output, "%s %s\n", username, password);
  344.   fclose(output);
  345.   }
  346. else
  347.   {
  348.   printf("Error: Unable to open output file!\n");
  349.   }
  350. }
  351.  
  352. /*
  353. ** This routine opens a passwd file, and parses it according to the
  354. ** following rules:
  355. **
  356. ** {user}{separator}{passwd field entry}{separator}
  357. ** There MUST be two separators per line..  the separator should be defined as
  358. ** SEPARATOR in the preprocessor.. usually ':' for UNIX-style passwd files.
  359. */
  360.  
  361. /*
  362. ** We use a state variable to define which part of the passwd entry we
  363. ** are currently processing..  it's more used as a sort of directive..
  364. ** if it's USER, store it in the user field of the struct passwd..
  365. ** etc etc..
  366. */
  367. struct passwd *parsepass(char *filename)
  368. {
  369. struct passwd *currentitem=NULL;
  370. struct passwd *firstitem=NULL;
  371. struct passwd *floatitem=NULL;
  372.  
  373. unsigned int counter = 0;
  374. unsigned int state;       /* the part of the field we're parsing right now */
  375. unsigned int ff = FALSE;
  376.  
  377. FILE *input;
  378. char temp;
  379.  
  380.  
  381. if (input = fopen(filename, "r"))
  382.   {
  383.   while ( 1 )
  384.     {
  385.     temp = fgetc(input);
  386.     if (feof(input)) break;
  387.     if (temp > 31 && temp < 127)
  388.       {
  389. /*
  390. ** ff here is being used as a sort of flip-flop switch. It is used for
  391. ** QUICKLY skipping over non-printable characters.
  392. */
  393.       if (ff == FALSE)
  394.         {
  395.         ff = TRUE;
  396.         if (!(floatitem = (struct passwd *)calloc(1, sizeof(struct passwd))))
  397.           {
  398.           printf("Error: Unable to allocate %d bytes. Exiting..\n", sizeof(struct passwd));
  399.           cleanup(firstitem);
  400.           }
  401.         state = USER;
  402.         }
  403.       if (state == USER)
  404.         {
  405.         if (temp != SEPARATOR && counter < NAMESIZE)
  406.           {
  407.           floatitem->name[counter++] = temp;
  408.           }
  409.         if (temp == SEPARATOR)
  410.           {
  411.           state = PASSWD;
  412.           counter = 0;
  413.           }
  414.         }
  415.       else if (state == PASSWD)
  416.         {
  417.         if (temp != SEPARATOR && counter < PASSWDSIZE)
  418.           {
  419.           if (counter < 2)
  420.             {
  421.             floatitem->salt[counter] = temp;
  422.             }
  423.           floatitem->password[counter++] = temp;
  424.           }
  425.         if (temp == SEPARATOR)
  426.           {
  427.           state = SAVE;
  428.           counter = 0;
  429.           }
  430.         }
  431.       if (state == SAVE)
  432.         {
  433.         if (!firstitem)
  434.           {
  435.           firstitem=floatitem;
  436.           }
  437.         else
  438.           {
  439.           currentitem=firstitem;
  440. /*
  441. ** We are using a doubly-linked list to store our list of passwd
  442. ** entries..  doubly-linked lists are cool! buhuhuhuhuhuhuhuhuh hehe
  443. */
  444.           while ( 1 )
  445.             {
  446.             if ((strcmp(floatitem->salt, currentitem->salt)) <= 0)
  447.               {
  448.               floatitem->nextitem=currentitem;
  449.               floatitem->lastitem=currentitem->lastitem;
  450.               currentitem->lastitem = floatitem;
  451.               if (floatitem->lastitem != NULL)
  452.                 {
  453.                 floatitem->lastitem->nextitem = floatitem;
  454.                 }
  455.               else
  456.                 {
  457.                 firstitem = floatitem;
  458.                 }
  459.               break;
  460.               }
  461.             if (currentitem->nextitem == NULL)
  462.               {
  463.               currentitem->nextitem = floatitem;
  464.               floatitem->lastitem = currentitem;
  465.               break;
  466.               }
  467.             currentitem=currentitem->nextitem;
  468.             }
  469.           }
  470.         state = DONE;
  471.         }
  472.       }
  473.     else
  474.       {
  475.       state = USER;
  476.       ff = FALSE;
  477.       }
  478.     }
  479.   fclose(input);
  480.   }
  481. else
  482.   {
  483.   printf("Error: Unable to open specified passwd file.\n");
  484.   }
  485. return(firstitem);
  486. }
  487.